<?php

namespace App\Http\Controllers\Wechat;

use App\Models\RegisterVerify;
use App\Models\UserInfo;
use App\Models\UserLibraryInfo;
use App\Models\UserSystemUnit;
use App\Models\UserWechatInfo;
use App\Models\UserWechatInfoTemp;
use App\Validate\WechatAuthValidate;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * 微信公众号授权登录   wx端
 * Class auth
 * @package app\Port\controller
 */
class WechatAuthController extends CommonController
{
    private $appid;
    private $appsecret;


    public $model = null;
    public $validate = null;

    public function __construct()
    {
        parent::__construct();
        $this->appid = config('other.appid');
        $this->appsecret = config('other.appsecret');

        $this->model = new UserWechatInfo();
        $this->validate = new WechatAuthValidate();
    }


    /**
     * 微信确认登陆后接受,获取信息  (微信公众号使用)  微信openid 作为主账号
     * @param code  微信code参数
     * @param invite  邀请码
     */
    public function indexInfo()
    {
        if (!$this->validate->scene('wx_auth')->check($this->request->all())) {
            return $this->returnApi(201,  $this->validate->getError());
        }

        $appid = $this->appid;
        $appsecret = $this->appsecret;

        $code = $this->request->code;/*code参数*/
        $invite = $this->request->invite;/*invite参数*/

        /*换取 access_token*/
        $json = request_url('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $appsecret . '&code=' . $code . '&grant_type=authorization_code');

        $arr = json_decode($json, true); //转化为数组

        if (empty($arr['access_token'])) {
            Log::error('授权失败，请联系管理员处理！' . date('Y-m-d H:i:s'));
            Log::error($arr);

            return $this->returnApi(202, '授权失败，请联系管理员处理！');
        }

        $access_token = $arr['access_token'];
        $openid = $arr['openid'];
        $unionid = !empty($arr['unionid']) ? $arr['unionid'] : null;

        /*传入token和openid 返回用户的信息*/
        $info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $openid . '⟨=zh_CN';
        $info = request_url($info_url);
        $info = json_decode($info, true);

        if (isset($info['nickname']) && isset($info['headimgurl'])) {
            // 启动事务
            DB::beginTransaction();
            try {
                /*检查是否已经绑定过账号*/
                $wechat = $this->model->change([
                    'nickname' => $info['nickname'],
                    'head_img' => $info['headimgurl'],
                    'open_id' => $openid,
                    'union_id' => $unionid,
                ]);

                if (empty($wechat['token'])) {
                    throw new Exception('登录失败');
                }
                $userInfoModel = new UserInfo();
                //邀请人加积分
                if (config('other.is_need_score') && $wechat['is_add'] && !empty($invite)) {
                    /**执行积分规则 */
                    //增加邀请人的积分
                    $invite_user_info = $userInfoModel->where('qr_code', $invite)->first();
                    if (!empty($invite_user_info['account_id'])) {
                        //添加邀请人数
                        $invite_user_info->invite_number = ++$invite_user_info->invite_number;
                        $invite_user_info->save();

                        $scoreRuleObj = new \App\Http\Controllers\ScoreRuleController();
                        $score_status = $scoreRuleObj->checkScoreStatus(2, $invite_user_info['id'], $invite_user_info['account_id']);

                        if ($score_status['code'] == 200) {
                            $system_id = $this->systemAdd($score_status['score_info']['type_name'], $invite_user_info['id'], $invite_user_info['account_id'], 11, 0, $score_status['score_info']['intro']);

                            $scoreRuleObj->scoreChange($score_status, $invite_user_info['id'], $invite_user_info['account_id'], $system_id); //添加积分消息
                        }
                    }

                    //写入用户信息表
                    $userInfoModel->where('wechat_id', $wechat['wechat_id'])->update([
                        'invite_user_id' => !empty($invite_user_info['id']) ? $invite_user_info['id'] : 0,
                        'invite_account_id' => !empty($invite_user_info['account_id']) ? $invite_user_info['account_id'] : 0,
                    ]);
                }

                $account_info = $userInfoModel->getAccountInfo($wechat['token']);
                if ($account_info) {
                    $account = $account_info['account'];
                } else {
                    $account = null;
                }

                DB::commit();
                return $this->returnApi(200, "授权成功", true, ['token' => $wechat['token'], 'qr_code' => $wechat['qr_code'], 'account' => $account, 'head_img' => $wechat['head_img'], 'nickname' => $wechat['nickname']]);
            } catch (\Exception $e) {
                // 回滚事务
                DB::rollBack();
                return $this->returnApi(202, '授权信息保存失败');
            }
        }
        return $this->returnApi(202, '授权信息保存失败');
    }


    /**
     * 微信确认登陆后接受,获取信息  (微信公众号使用)  需要绑定电话号码，电话号码作为主账号  积分在用户表
     * @param code  微信code参数
     * @param invite  邀请码
     */
    public function indexInfoNeedTel()
    {
        if (!$this->validate->scene('wx_auth')->check($this->request->all())) {
            return $this->returnApi(201,  $this->validate->getError());
        }

        $appid = $this->appid;
        $appsecret = $this->appsecret;

        $code = $this->request->code;/*code参数*/
        $invite = $this->request->invite;/*invite参数*/

        /*换取 access_token*/
        $json = request_url('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $appsecret . '&code=' . $code . '&grant_type=authorization_code');

        $arr = json_decode($json, true); //转化为数组

        if (empty($arr['access_token'])) {
            Log::error('授权失败，请联系管理员处理！' . date('Y-m-d H:i:s'));
            Log::error($arr);

            return $this->returnApi(202, '授权失败，请联系管理员处理！');
        }

        $access_token = $arr['access_token'];
        $openid = $arr['openid'];
        $unionid = !empty($arr['unionid']) ? $arr['unionid'] : null;

        /*传入token和openid 返回用户的信息*/
        $info_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $openid . '⟨=zh_CN';
        $info = request_url($info_url);
        $info = json_decode($info, true);

        if (isset($info['nickname']) && isset($info['headimgurl'])) {
            // 启动事务
            DB::beginTransaction();
            try {
                $userWechatInfoTempModel = new UserWechatInfoTemp();
                /*检查是否已经绑定过账号*/
                $userWechatInfoTempModel->change([
                    'nickname' => $info['nickname'],
                    'head_img' => $info['headimgurl'],
                    'open_id' => $openid,
                    'union_id' => $unionid,
                    'invite' => $invite,
                ]);

                $token = null;
                $head_img = $info['headimgurl'];
                $nickname = $info['nickname'];
                $account_qr_url = null;
                $account = null;
                $username = null;

                //判断当前openid 是否绑定了手机号码
                $wechat_id = $this->model->where('open_id', $openid)->value('id');
                if ($wechat_id) {
                    $user_info = UserInfo::where('wechat_id', $wechat_id)->first();
                    if ($user_info) {
                        $token = $user_info['token'];
                        $head_img = $user_info['head_img'];
                        $nickname = $user_info['nickname'];
                        if (!empty($user_info['account_id'])) {
                            $library_info = UserLibraryInfo::where('id', $user_info['account_id'])->first();
                            $account_qr_url = $library_info['qr_url'] ?? null; //读者证二维码
                            $account = $library_info['account'] ?? null;
                            $username = $library_info['username'] ?? null;
                        }
                    }
                }

                DB::commit();
                return $this->returnApi(200, "授权成功", true, [
                    'openid' => $openid,
                    'token' => $token,
                    'head_img' => $head_img,
                    'nickname' => $nickname,
                    'account_qr_url' => $account_qr_url,
                    'account' => $account,
                    'username' => $username,
                ]);
            } catch (\Exception $e) {
                // 回滚事务
                DB::rollBack();
                return $this->returnApi(202, '授权信息保存失败');
            }
        }
        return $this->returnApi(202, '授权信息保存失败');
    }


    /**
     * 微信确认登陆后接受,获取信息  (微信公众号-用户静默授权 使用)
     * @param code  微信code参数
     * @param invite  邀请码
     */
    public function silentIndexInfo()
    {
        if (!$this->validate->scene('wx_auth')->check($this->request->all())) {
            return $this->returnApi(201,  $this->validate->getError());
        }

        $appid = $this->appid;
        $appsecret = $this->appsecret;

        $code = $this->request->code;/*code参数*/
        $invite = $this->request->invite;/*invite参数*/
        /*换取 access_token*/
        $json = request_url('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $appsecret . '&code=' . $code . '&grant_type=authorization_code');
        $arr = json_decode($json, true); //转化为数组

        if (!empty($arr['openid'])) {
            // 启动事务
            DB::beginTransaction();
            try {
                $nickname = $this->model->getNickname(); //获取随机昵称
                $head_img = $this->getImgAddrUrl() . 'default/default_head_img.png'; //默认头像
                /*检查是否已经绑定过账号*/
                $wechat = $this->model->change([
                    'nickname' => $nickname,
                    'head_img' => $head_img,
                    'open_id' => $arr['openid'],
                ]);

                if (empty($wechat['token'])) {
                    throw new Exception('登录失败');
                }
                $userInfoModel = new UserInfo();
                //邀请人加积分
                if (config('other.is_need_score') && $wechat['is_add'] && !empty($invite)) {
                    /**执行积分规则 */
                    //增加邀请人的积分
                    $invite_user_info = $userInfoModel->where('qr_code', $invite)->first();
                    if (!empty($invite_user_info['account_id'])) {
                        //添加邀请人数
                        $invite_user_info->invite_number = ++$invite_user_info->invite_number;
                        $invite_user_info->save();

                        $scoreRuleObj = new \App\Http\Controllers\ScoreRuleController();
                        $score_status = $scoreRuleObj->checkScoreStatus(2, $invite_user_info['id'], $invite_user_info['account_id']);

                        if ($score_status['code'] == 200) {
                            $system_id = $this->systemAdd($score_status['score_info']['type_name'], $invite_user_info['id'], $invite_user_info['account_id'], 11, 0, $score_status['score_info']['intro']);

                            $scoreRuleObj->scoreChange($score_status, $invite_user_info['id'], $invite_user_info['account_id'], $system_id); //添加积分消息
                        }
                    }

                    //写入用户信息表
                    $userInfoModel->where('wechat_id', $wechat['wechat_id'])->update([
                        'invite_user_id' => !empty($invite_user_info['id']) ? $invite_user_info['id'] : 0,
                        'invite_account_id' => !empty($invite_user_info['account_id']) ? $invite_user_info['account_id'] : 0,
                    ]);
                }

                $account_info = $userInfoModel->getAccountInfo($wechat['token']);
                if ($account_info) {
                    $account = $account_info['account'];
                } else {
                    $account = null;
                }

                DB::commit();
                return $this->returnApi(200, "授权成功", true, ['token' => $wechat['token'], 'qr_code' => $wechat['qr_code'], 'account' => $account, 'head_img' => $wechat['head_img'], 'nickname' => $wechat['nickname']]);
            } catch (\Exception $e) {
                // 回滚事务
                DB::rollBack();
                return $this->returnApi(202, '授权信息保存失败');
            }
        }

        Log::error('授权失败，请联系管理员处理！' . date('Y-m-d H:i:s'));
        Log::error($arr);
        return $this->returnApi(202, '授权失败 - ' . $arr['errmsg']);
    }


    /**
     * 微信授权完，绑定手机号码
     * @param $open_id   微信授权open_id
     * @param $tel       手机号码       必传
     * @param $verify    验证码
     */
    public function bindPhoneNumber()
    {
        //增加验证场景进行验证
        if (!$this->validate->scene('wx_bind_phone_number')->check($this->request->all())) {
            return $this->returnApi(201,  $this->validate->getError());
        }
        //单独验证身份证正反面是否必传
        $open_id = $this->request->open_id;
        $tel = $this->request->tel;

        DB::beginTransaction();
        try {
            RegisterVerify::where('phone', $this->request->tel)->delete(); //验证成功，删除验证码
            $user_info = $this->model->changeByTel(['open_id' => $open_id, 'tel' => $tel]);

            //添加用户到单位
            // $userSystemUnitModel = new UserSystemUnit();
            // $userSystemUnitModel->addUserSystemUnit($user_info['user_id'], $this->request->system_unit_id, $user_info['source_invite']);

            $account_qr_url = null;
            $account = null;
            $username = null;
            if (!empty($user_info['account_id'])) {
                $library_info = UserLibraryInfo::where('id', $user_info['account_id'])->first();
                $account_qr_url = $library_info['qr_url'] ?? null; //读者证二维码
                $account = $library_info['account'] ?? null;
                $username = $library_info['username'] ?? null;
            }
            DB::commit();
            return $this->returnApi(200, "绑定成功", true, [
                'token' => $user_info['token'],
                'qr_code' => $user_info['qr_code'],
                'head_img' =>  $user_info['head_img'],
                'nickname' =>  $user_info['nickname'],
                'account_qr_url' => $account_qr_url,
                'account' => $account,
                'username' => $username,
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->returnApi(202, $e->getMessage() . $e->getFile() . $e->getLine());
        }
    }
    /**
     * 退出微信公众号登录 (小程序禁止调用此接口)
     * @param token  用户token
     */
    public function wxLogout()
    {
        $user_id = $this->request->user_info['id'];

        $userInfoModel = new UserInfo();
        $user_info = $userInfoModel->where('id', $user_id)->first();
        if (empty($user_info['wechat_id'])) {
            return $this->returnApi(200, '退出成功', true);
        }

        DB::beginTransaction();
        try {
            $userWechatInfoModel = new UserWechatInfo();
            $user_wechat_info = $userWechatInfoModel->where('id', $user_info['wechat_id'])->first();
            $user_wechat_info->old_open_id = $user_wechat_info->open_id;
            $user_wechat_info->open_id = null;
            $user_wechat_info->union_id = null;
            $user_wechat_info->nickname = null;
            $user_wechat_info->head_img = null;
            $user_wechat_info->save();

            //去掉用户表的 微信登录信息
            $user_info->wechat_id = null;
            $user_info->save();

            DB::commit();
            return $this->returnApi(200, "退出成功", true);
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->returnApi(202, $e->getMessage() . $e->getFile() . $e->getLine());
        }
    }
}
